package com.chisheng.caa.service;

import cn.hutool.core.util.IdUtil;
import com.chisheng.caa.exception.DuplicateValueException;

import java.util.Objects;

/**
 * 缓存访问工具接口
 */
public interface CacheUtil {

    /**
     * 返回缓存对象。缓存不存在或过期返回 null。
     *
     * @param accessKey 缓存访问键
     * @param <T>       对象类型
     * @return 缓存实例或 null
     */
    <T> T get(String accessKey);

    /**
     * 返回缓存对象。键不存在抛出异常。
     *
     * @param accessKey 缓存访问键
     * @param <T>       对象类型
     * @return 缓存实例
     * @throws NullPointerException 缓存不存在时抛出
     */
    default <T> T checkAndGet(String accessKey) {
        return Objects.requireNonNull(get(accessKey), String.format("无效访问键 '%s'", accessKey));
    }

    /**
     * 设置缓存对象。访问键不能重复。
     *
     * @param accessKey  缓存访问键
     * @param obj        缓存对象
     * @param expiryTime 缓存过期时间。取值 -1 不会过期。
     * @throws DuplicateValueException 访问键重复时抛出
     */
    void put(String accessKey, Object obj, long expiryTime);

    /**
     * 设置缓存对象。由雪花算法生成访问键。
     *
     * @param obj        缓存对象
     * @param expiryTime 缓存过期时间。取值 -1 不会过期。
     * @return 缓存访问键
     */
    default String put(Object obj, long expiryTime) {
        String accessKey = IdUtil.getSnowflakeNextIdStr();
        put(accessKey, obj, expiryTime);
        return accessKey;
    }

    /**
     * 设置缓存对象。由雪花算法生成访问键。默认配置过期时间。
     *
     * @param obj 缓存对象
     * @return 缓存访问键
     */
    default String put(Object obj) {
        throw new UnsupportedOperationException();
    }

    /**
     * 移除缓存对象。忽略缓存不存在或过期。
     *
     * @param accessKey 缓存访问键
     */
    void remove(String accessKey);

}
